iT邦幫忙

2026 iThome 鐵人賽

DAY 2
0
Software Development

《醫資生的 FHIR 30日入門:用 Postman 讀懂醫療資料交換》系列 第 13

Day 13|REST API是什麼?用餐廳點餐來理解

  • 分享至 

  • xImage
  •  

前言

前幾天的文章主要在認識FHIR的資料結構,包括:

  • Resource
  • JSON
  • 資料型別
  • Reference
  • 醫療代碼

我們已經知道Patient Resource可以表示病人基本資料,Observation可以表示檢驗或生命徵象,也能透過Reference建立Resource之間的關係。

但資料準備好之後,系統要如何讀取或傳送這些Resource?

這時就會使用API。

FHIR可以透過RESTful API操作Resource,例如讀取病人、搜尋檢驗結果或新增一筆就醫資料。

今天先不急著打開Postman,而是用餐廳點餐的方式理解API、REST、Client、Server、Request、Response及Endpoint。


API是什麼?

API的全名是:

Application Programming Interface

中文通常稱為「應用程式介面」。

API提供一套規則,讓不同程式可以互相提出要求及取得結果。

例如,手機上的天氣App不一定自己在手機裡測量全世界的氣溫,而是向天氣服務的API提出Request,再取得天氣資料。

在醫療資訊情境中,也可能發生:

  • 掛號系統向病人資料服務查詢基本資料。
  • App向FHIR Server取得病人的檢驗結果。
  • 醫院入口網站查詢病人的門診預約。
  • 系統將新的Observation傳送到FHIR Server。
  • 跨院應用程式在取得授權後讀取健康資料。

API就像兩套系統之間事先約定好的服務窗口。


用餐廳點餐理解API

假設我走進一家餐廳,想要點一份餐點。

正常情況下,我不會直接進入廚房翻冰箱、開瓦斯爐,也不會自己修改餐廳的訂單系統。

我會先查看菜單,告訴服務人員想點什麼,再等待廚房準備餐點。

可以將這個過程對應成API:

餐廳情境 API概念
顧客 Client
服務人員及點餐窗口 API
菜單 API規格或文件
廚房及餐廳系統 Server
顧客點餐 Request
餐點或回覆 Response
餐點名稱及客製需求 Request參數
餐點售完或點餐錯誤 錯誤Response

顧客不需要知道廚房內部如何管理食材,只要依照菜單及點餐規則提出要求。

同樣地,Client通常不需要直接操作Server的資料庫,而是依照API規則提出Request。


Client是什麼?

Client是提出Request的一方。

Client不一定是一台個人電腦,也可能是:

  • 瀏覽器
  • 手機App
  • Postman
  • 醫院資訊系統
  • 另一台Server
  • 使用Java、Python或C#撰寫的程式

在餐廳比喻中,Client就是點餐的顧客。

在FHIR情境中,假設Postman送出請求,要求讀取一筆Patient Resource,那麼Postman就是Client。

Postman → FHIR Server

Server是什麼?

Server是接收Request並提供服務的一方。

它可能負責:

  • 接收API請求
  • 檢查請求格式
  • 驗證使用者身分
  • 確認存取權限
  • 查詢或更新資料
  • 產生Response
  • 回報成功或錯誤

在餐廳比喻中,Server可以想成包含廚房、食材及訂單處理流程的餐廳系統。

在FHIR情境中,FHIR Server會接收Client的請求,並依照支援的功能處理Patient、Observation或其他Resource。


Request是什麼?

Request是Client傳送給Server的要求。

例如:

請給我ID為patient-001的Patient Resource。

轉換成HTTP請求,可以表示為:

GET https://hospital.example.org/fhir/Patient/patient-001

一個HTTP Request通常包含幾個重要部分:

  • HTTP方法
  • URL
  • Headers
  • Body
  • 查詢參數

不是每一個Request都會同時使用全部內容。


HTTP方法

HTTP方法用來表示Client想對資料執行什麼操作。

常見方法包括:

HTTP方法 常見用途
GET 讀取或搜尋資料
POST 建立資料
PUT 更新或建立指定位置的資料
DELETE 刪除資料

例如:

GET /Patient/patient-001

代表讀取Patient。

POST /Patient

可能代表建立新的Patient。

FHIR對每種HTTP方法及Resource操作有更明確的規則,會在下一篇文章詳細介紹。


URL是Request的目的地

URL用來告訴Client要向哪個位置提出要求。

例如:

https://hospital.example.org/fhir/Patient/patient-001

可以拆成:

部分 內容 用途
通訊協定 https 表示使用HTTPS
網域 hospital.example.org Server位置
基礎路徑 /fhir FHIR服務位置
Resource類型 /Patient 要操作Patient
Resource id /patient-001 指定某筆Patient

其中:

https://hospital.example.org/fhir

可以稱為FHIR Server的Base URL。

再加上:

/Patient/patient-001

就指向一筆特定Patient Resource。


Endpoint是什麼?

Endpoint可以理解為API提供服務的特定位置。

例如:

https://hospital.example.org/fhir/Patient

是與Patient Resource相關的Endpoint。

https://hospital.example.org/fhir/Observation

是與Observation Resource相關的Endpoint。

加上id後:

https://hospital.example.org/fhir/Patient/patient-001

就指向特定Patient。

用餐廳比喻來說,Endpoint有點像菜單上不同的點餐項目或服務窗口。Client必須前往正確位置,Server才知道要處理哪一類資料。


Headers是什麼?

Headers用來提供與Request或Response有關的附加資訊。

它們比較像包裹外面的標籤,告訴接收方如何處理內容。

FHIR API中可能使用:

Accept: application/fhir+json

表示Client希望Server回傳FHIR JSON。

如果Request Body中放入FHIR JSON,可能使用:

Content-Type: application/fhir+json

表示Client傳送的內容是FHIR JSON。

部分API也可能透過Header傳送授權資訊,例如:

Authorization: Bearer <access-token>

不過,真正的Token不能公開放在文章、截圖或程式碼中。


Accept與Content-Type有什麼不同?

這兩個Header很容易混淆。

Accept

Accept: application/fhir+json

代表:

我希望收到FHIR JSON格式的Response。

Content-Type

Content-Type: application/fhir+json

代表:

我現在送出的Request Body是FHIR JSON格式。

可以用點餐比喻:

  • Accept:我希望餐點用紙盒包裝。
  • Content-Type:我現在交給你的內容是紙本點餐單。

如果是單純GET資料,通常沒有Request Body,因此不一定需要設定Content-Type;但仍可以使用Accept告訴Server希望收到的格式。


Request Body是什麼?

Body是Request中實際傳送的主要內容。

例如,要建立一筆Patient Resource時,Request Body可能包含:

{
  "resourceType": "Patient",
  "active": true,
  "name": [
    {
      "text": "王小明"
    }
  ]
}

Body比較常出現在POST或PUT等需要傳送資料的操作中。

GET通常用來取得資料,一般不會依賴Request Body。

用餐廳比喻來說,Body就像點餐單上的詳細內容,包括餐點、數量及客製需求。


查詢參數是什麼?

如果不是讀取已知id的Patient,而是想搜尋符合條件的資料,可以在URL後加入查詢參數。

例如:

GET https://hospital.example.org/fhir/Patient?name=王小明

其中:

?name=王小明

就是查詢參數。

可以拆成:

  • ?:表示後面開始進入查詢參數。
  • name:參數名稱。
  • 王小明:參數值。
  • =:連接參數名稱及值。

如果有多個條件,可以使用&連接:

GET https://hospital.example.org/fhir/Patient?name=王小明&birthdate=2000-01-01

表示同時使用姓名及出生日期搜尋Patient。

實際支援哪些搜尋參數,必須查看FHIR規範及該FHIR Server的CapabilityStatement。


Response是什麼?

Response是Server處理Request後傳回Client的結果。

假設Client送出:

GET https://hospital.example.org/fhir/Patient/patient-001

Server可能回傳:

{
  "resourceType": "Patient",
  "id": "patient-001",
  "active": true,
  "name": [
    {
      "text": "王小明"
    }
  ]
}

這份Patient Resource就是Response Body的一部分。

一個HTTP Response通常包含:

  • Status Code
  • Headers
  • Body

Status Code:Server處理得怎麼樣?

Status Code是由三位數字組成的HTTP狀態碼,用來表示Request的處理結果。

常見狀態包括:

Status Code 常見意義
200 OK Request成功
201 Created 資料建立成功
400 Bad Request Request內容有問題
401 Unauthorized 尚未完成有效身分驗證
403 Forbidden 已辨識身分但沒有權限
404 Not Found 找不到指定Resource
500 Internal Server Error Server內部發生錯誤

例如,讀取存在的Patient可能得到:

200 OK

讀取不存在的Patient可能得到:

404 Not Found

狀態碼只能先提供大方向,實際錯誤原因仍可能出現在Response Body中。

FHIR Server發生錯誤時,可能回傳OperationOutcome Resource,提供更詳細的問題說明。


一次完整的API溝通流程

假設我們想讀取王小明的Patient Resource。

第一步:Client建立Request

GET https://hospital.example.org/fhir/Patient/patient-001
Accept: application/fhir+json

第二步:Request送到FHIR Server

FHIR Server收到要求後,確認:

  • 是否支援Patient Resource
  • 是否支援read操作
  • Client是否具有權限
  • patient-001是否存在

第三步:Server建立Response

如果成功,可能回傳:

200 OK
Content-Type: application/fhir+json

Response Body:

{
  "resourceType": "Patient",
  "id": "patient-001",
  "active": true,
  "name": [
    {
      "text": "王小明"
    }
  ]
}

第四步:Client處理Response

Postman可以直接顯示JSON;App則可以將姓名及其他資料呈現在使用者介面上。

整個流程可以簡化成:

Client送出Request
        ↓
FHIR Server處理
        ↓
Server回傳Response
        ↓
Client顯示或使用資料

API和REST有什麼不同?

API是一個較廣泛的概念,代表應用程式之間互動的介面。

REST則是一種軟體架構風格,完整名稱是:

Representational State Transfer

符合REST設計概念的API,通常稱為RESTful API。

REST經常使用HTTP,並將要操作的內容視為Resource。

例如:

/Patient

代表Patient這類Resource。

/Patient/patient-001

代表一筆特定Patient Resource。

再搭配HTTP方法表達操作:

GET /Patient/patient-001

讀取Patient。

DELETE /Patient/patient-001

要求刪除Patient。

所以API不一定都是REST API,而REST API是API的一種設計方式。


FHIR和REST API的關係

FHIR定義了一套RESTful API,讓Client可以對Resource執行不同互動。

例如:

需求 FHIR API示意
讀取Patient GET /Patient/patient-001
搜尋Patient GET /Patient?name=王小明
建立Patient POST /Patient
更新Patient PUT /Patient/patient-001
刪除Patient DELETE /Patient/patient-001
查看Server能力 GET /metadata

FHIR使用Resource作為資料模型,再透過HTTP及RESTful API提供操作方式。

不過,FHIR Server不一定支援所有Resource及操作。實際支援內容應查看Server提供的CapabilityStatement。


REST API不等於直接連接資料庫

Client呼叫:

GET /Patient/patient-001

不代表Client直接進入Server的資料庫。

FHIR Server可能在背後:

  • 查詢自己的FHIR資料庫
  • 從醫院既有系統取得資料
  • 將院內格式轉換成FHIR
  • 呼叫其他服務
  • 確認存取權限
  • 過濾不能提供的欄位
  • 產生符合Profile的Resource

Client只需要依照API規格提出要求,不需要知道Server內部如何完成。

這就像顧客只依照菜單點餐,不需要進入廚房了解廚師如何取得及處理每一種食材。


API文件就像菜單

顧客如果沒有菜單,就不知道餐廳提供哪些餐點。

同樣地,開發者需要API文件才能知道:

  • Base URL是什麼?
  • 有哪些Endpoint?
  • 支援哪些HTTP方法?
  • 可以使用哪些參數?
  • Request Body格式是什麼?
  • Response會回傳什麼?
  • 需要哪些身分驗證?
  • 可能出現哪些錯誤?

在FHIR中,除了官方規範外,每台FHIR Server也應該透過CapabilityStatement說明自己支援的Resource、操作及功能。

因此,不能只知道對方是FHIR Server,就假設所有Server的功能都完全相同。


API安全不能忽略

如果FHIR Server保存真實醫療資料,不能讓所有人只知道網址就自由查詢。

正式環境通常還需要處理:

  • 使用者身分驗證
  • 存取權限
  • 病人同意
  • HTTPS加密
  • Access Token
  • 操作紀錄
  • 存取範圍
  • 資料最小化
  • Token及帳號安全

本系列後續實作會使用公開測試伺服器及完全虛構的資料。

公開測試Server可能不要求登入,但這不代表正式醫療系統也能在沒有驗證的情況下提供資料。


用餐廳比喻整理一次

API概念 餐廳情境 FHIR情境
Client 顧客 Postman或醫療App
Server 餐廳及廚房 FHIR Server
API 點餐服務 FHIR API
API文件 菜單及點餐規則 FHIR規範及CapabilityStatement
Endpoint 指定點餐項目或窗口 /Patient
Request 顧客提出點餐 GET /Patient/123
Header 包裝、身分或格式要求 Accept: application/fhir+json
Body 點餐的詳細內容 Patient JSON
Response 餐點或店員回覆 FHIR Resource或錯誤資訊
Status Code 成功、售完或無法供應 200、404或其他狀態碼

今日練習

請觀察以下Request:

GET https://hospital.example.org/fhir/Observation?patient=patient-001
Accept: application/fhir+json

可以找出:

  1. Client想執行GET操作。
  2. FHIR Server的Base URL是:
https://hospital.example.org/fhir
  1. 要操作的Resource類型是:
Observation
  1. 查詢參數是:
patient=patient-001
  1. Client希望收到FHIR JSON:
Accept: application/fhir+json

整個Request的意思是:

請搜尋與patient-001這位病人有關的Observation,並以FHIR JSON格式回傳。


今日小結

今天使用餐廳點餐的比喻,認識了REST API的基本概念。

  • Client是提出要求的一方。
  • Server是接收並處理要求的一方。
  • Request是Client送出的要求。
  • Response是Server回傳的結果。
  • Endpoint是API提供服務的位置。
  • Headers提供格式、授權等附加資訊。
  • Body包含要傳送的主要資料。
  • Status Code說明Request的處理結果。

FHIR以Resource作為資料模型,並提供RESTful API操作Patient、Observation及其他Resource。

今天先建立API溝通的整體概念,下一篇將更詳細地比較GET、POST、PUT及DELETE,並認識常見HTTP狀態碼及FHIR的OperationOutcome。

明日預告

Day 14|GET、POST、PUT、DELETE有什麼不同?

參考資料

  1. HL7 FHIR R4:RESTful API
    https://hl7.org/fhir/R4/http.html

  2. HL7 FHIR R4:FHIR Overview for Developers
    https://hl7.org/fhir/R4/overview-dev.html

  3. HL7 FHIR R4:CapabilityStatement
    https://hl7.org/fhir/R4/capabilitystatement.html

  4. HL7 FHIR R4:OperationOutcome
    https://hl7.org/fhir/R4/operationoutcome.html

  5. RFC 9110:HTTP Semantics
    https://www.rfc-editor.org/rfc/rfc9110


上一篇
Day 12|醫療代碼為什麼這麼重要?
下一篇
Day 14|GET、POST、PUT、DELETE有什麼不同?
系列文
《醫資生的 FHIR 30日入門:用 Postman 讀懂醫療資料交換》30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言